package org.xtext.runtime.plan;

import is.lill.acre.message.IACREMessage;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.xtext.runtime.formula.Predicate;
import org.xtext.runtime.interpreter.Agent;
import org.xtext.runtime.messaging.AstraMessage;
import org.xtext.runtime.term.ITerm;
import org.xtext.runtime.term.Term;
import org.xtext.runtime.term.Variable;
import org.xtext.runtime.util.Bindings;
import org.xtext.runtime.util.EvaluateTermsVisitor;

/**
 * Implements the plan step for invoking acre_cancel
 * 
 * @author rem &amp; daithi
 * 
 */
public class AcreCancelStep implements IPlanStep {
   private ITerm cid;

   public AcreCancelStep( ITerm cid ) {
      this.cid = cid;
   }

   @Override
   public AcreCancelStep apply( Bindings set ) {
      cid = cid.apply( set );
      return this;
   }

   @SuppressWarnings ( "unchecked")
   @Override
   public void handle( Agent agent, PlanStack planStack ) {
      EvaluateTermsVisitor visitor = new EvaluateTermsVisitor( agent );
      Term<String> c_id = (Term<String>) cid.accept( visitor );

      IACREMessage am = agent.getConversationManager().cancel( c_id.value() );
      if ( am != null ) {
         AstraMessage toSend = new AstraMessage();
         toSend.setPerformative( am.getPerformative() );
         toSend.setSender( am.getSender().getName() );
         toSend.addReceiver( am.getReceiver().getName() );
         toSend.setContent( null ); // ACRE cancel messages have no content
         toSend.setLanguage( am.getLanguage() );
         toSend.setProtocol( am.getProtocol().toString() );
         toSend.setConversationId( am.getConversationIdentifier() );
         toSend.setContent( new Predicate( "", new ITerm[0] ) );
         
         agent.messageService().send( toSend ); // we only have local message passing so this never returns false
      }
      else {
         agent.addBelief( new Predicate( "cancelFailed", new ITerm[] { Term.newInstance( c_id.value() ) } ) );
         planStack.fail();
      }
   }

   @Override
   public String toString( String tabs ) {
      return tabs + "acre_cancel(" + cid + ")";
   }

   public String toFullString( String tabs ) {
      return toString( tabs );
   }

   @Override
   public Set<Variable> variables() {
      Set<Variable> vars = new HashSet<Variable>();
      if ( cid instanceof Variable )
         vars.add( (Variable) cid );
      return vars;
   }

   @Override
   public AcreCancelStep copy( Map<String, Variable> vars ) {
      return new AcreCancelStep( cid.copy( vars ) );
   }

   public String toString() {
      return toString( "" );
   }

   @Override
   public void reset() {}
}